package com.fifth.apartment.config;

import cn.hutool.json.JSONUtil;
import com.fifth.apartment.constant.RedisMessageConstant;
import com.fifth.apartment.entity.User;
import com.fifth.apartment.utils.JwtHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

/**
 * @Author chenmin
 * @Description token认证过滤器
 * @Date 2023/12/22
 *
 * 作用：解析请求头中的token，并验证合法性。
 * 继承 OncePerRequestFilter 保证请求经过过滤器一次
 */

@Component
@Slf4j
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        log.info("getRequestURI:"+request.getRequestURI());
        //1.对白名单请求进行放行
        if (request.getRequestURI().equals("/admin/user/login")||
                request.getRequestURI().equals("/admin/user/phone")||
                request.getRequestURI().equals("/admin/user/code")){
            filterChain.doFilter(request,response);
            return;
        }

        //2.获取请求头中的tocken，若没有tocken也进行放行，由失败处理器来进行处理
        String token = null;
        Cookie[] cookies = request.getCookies();
        if (cookies!=null){
            String[] split = cookies[0].getValue().split(":");
            String[] split1 = split[1].split("%22");
            token= split1[1];
        }
        if (!StringUtils.hasLength(token)){
            filterChain.doFilter(request,response);
            return;
        }

        //3.有token JWT工具类解析token中的userId
        Integer userId = null;
        try {
            userId = JwtHelper.getMemberId(token);
            log.info(""+userId);
        } catch (Exception e) {
            log.info("非法token");
            e.printStackTrace();
        }

        //4.从redis中获取用户信息 若不存在直接抛出异常
        String tokenKey = RedisMessageConstant.LONGIN_USER_TOKEN + "::" + userId;
        Object o = redisTemplate.opsForValue().get(tokenKey);//user对象的json字符串
        if(Objects.isNull(o)){
            log.info("Redis中未获取到管理员的信息，请重新登录！");
        }
        //若存在则将Authentication对象（用户信息、已认证状态、权限信息）存入 SecurityContextHolder
        //json字符串 转换为 User对象
        User user = JSONUtil.toBean(o.toString(), User.class);
        LoginUser loginUser = new LoginUser(user);
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        //放行 ==》到认证过滤器 UsernamePasswordAuthenticationFilter
        filterChain.doFilter(request, response);
    }
}
